﻿using Rhino.Mocks;
using WroxGallery.Controllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using WroxGallery.Models.Interfaces;
using System.Web.Mvc;

namespace WroxGallery.Tests.Controllers
{

    [TestClass()]
    public class AccountControllerTest
    {   
        private MockRepository mocks;
        private IFormsAuthentication formsAuth;
        private IConfigurationRepository provider;

        [TestInitialize]
        public void SetupMocks()
        {
            mocks = new MockRepository();
            formsAuth = mocks.DynamicMock<IFormsAuthentication>();
            provider = mocks.DynamicMock<IConfigurationRepository>();
        }

        [TestMethod]
        public void AccountController_Logout_Action_LogsOut_And_Redirect_To_Home()
        {
            using (mocks.Record())
            {
                Expect.Call(delegate { formsAuth.SignOut(); });
            }

            AccountController controller = new AccountController(formsAuth, provider);
            using (mocks.Playback())
            {
                RedirectToRouteResult result = controller.LogOff() as RedirectToRouteResult;
                Assert.IsNotNull(result, "Not a redirect result");

                Assert.AreEqual("Index", result.RouteValues["Action"]);
                Assert.AreEqual("Home", result.RouteValues["Controller"]);
            }
        }

        [TestMethod]
        public void AccountController_Valid_Credentials_Redirects_To_Admin_Index_Page()
        {
            string username = "admin";
            string password = "admin";

            using (mocks.Record())
            {
                Expect.Call(provider.ValidateUser(username, password)).Return(true);
                Expect.Call(delegate { formsAuth.SignIn(username, false); });
            }

            AccountController controller = new AccountController(formsAuth, provider);
            
            using (mocks.Playback())
            {
                RedirectToRouteResult result = controller.LogOn(username, password, false,"") as RedirectToRouteResult;
                Assert.IsNotNull(result, "Not a redirect result");

                Assert.AreEqual("Index", result.RouteValues["Action"]);
                Assert.AreEqual("Admin", result.RouteValues["Controller"]);
            }
        }

        [TestMethod]
        public void AccountController_Valid_Credentials_And_ReturnUrl_Redirects_To_ReturnUrl()
        {
            string username = "admin";
            string password = "admin";

            using (mocks.Record())
            {
                Expect.Call(provider.ValidateUser(username, password)).Return(true);
                Expect.Call(delegate { formsAuth.SignIn(username, false); });
            }

            AccountController controller = new AccountController(formsAuth, provider);

            using (mocks.Playback())
            {
                RedirectResult result = controller.LogOn(username, password, false, "http://localhost/Admin/Index") as RedirectResult;
                Assert.IsNotNull(result, "Not a redirect result");

                Assert.AreEqual("http://localhost/Admin/Index", result.Url);
            }
        }


        [TestMethod]
        public void AccountController_Invalid_Credentials_RendersView_With_ModelError()
        {
            string username = "admin";
            string password = "admin";

            using (mocks.Record())
            {
                Expect.Call(provider.ValidateUser(username, password)).Return(false);
            }

            AccountController controller = new AccountController(formsAuth, provider);

            using (mocks.Playback())
            {
                ViewResult result = controller.LogOn(username, password, false, "") as ViewResult;
                Assert.IsNotNull(result, "Not a view result");

                Assert.AreEqual("",result.ViewName);
                Assert.IsNotNull(result.ViewData.ModelState["_FORM"]);
            }
        }
    }
}